﻿using System.Diagnostics;
using System.Threading.Tasks.Sources;

namespace Test003
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //int num = 0;
            //_ = Task.Factory.StartNew(() =>
            //{
            //    Stopwatch sw = Stopwatch.StartNew();
            //    while (true)
            //    {
            //        Thread.Sleep(5000);
            //        double speed = num / sw.Elapsed.TotalSeconds;
            //        Console.WriteLine($"10000个循环干活总速度={speed:#### ####.0} 次/秒");
            //    }
            //}, TaskCreationOptions.LongRunning);

            TimeSpan delay = TimeSpan.FromMilliseconds(15d);
            for (int i = 0; i < 10000; i++)
            {
                _ = func(i, delay);
            }

            Console.WriteLine("开始");
            Console.ReadLine();
        }

        async static ValueTask func(int i, TimeSpan delay)
        {
            using var taskSource = new DelayTaskSource();
            while (true)
            {
                await taskSource.CreateDelayTask(delay);
                // Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.ffff} - {i}");

                // num++; // 干活
            }
        }
    }

    sealed class DelayTaskSource : IValueTaskSource, IDisposable
    {
        private readonly Timer timer;
        private ManualResetValueTaskSourceCore<object?> sourceCore = new();

        public DelayTaskSource()
        {
            this.timer = new Timer(this.TimerCallback, null, Timeout.Infinite, Timeout.Infinite);
        }

        private void TimerCallback(object? state)
        {
            this.sourceCore.SetResult(null);
        }

        public ValueTask CreateDelayTask(TimeSpan delay)
        {
            this.sourceCore.Reset();
            this.timer.Change(delay, Timeout.InfiniteTimeSpan);
            return new ValueTask(this, this.sourceCore.Version);
        }

        public void GetResult(short token)
        {
            sourceCore.GetResult(token);
        }

        public ValueTaskSourceStatus GetStatus(short token)
        {
            return sourceCore.GetStatus(token);
        }

        public void OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags)
        {
            sourceCore.OnCompleted(continuation, state, token, flags);
        }

        public void Dispose()
        {
            this.timer.Dispose();
        }
    }
}
